package com.hospital.ecard.cardhandler;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.hospital.common.core.module.controller.vo.PatientReqEntity;
import com.hospital.common.core.module.entity.ecard.*;
import com.hospital.common.core.result.Tip;
import com.hospital.common.core.utils.*;
import com.hospital.ecard.config.properties.DingDingProperty;
import com.hospital.ecard.module.controller.CardController;
import com.hospital.ecard.module.entity.PatientInfo;
import com.hospital.ecard.module.service.PatientInfoService;
import com.hospital.ecard.patienthandler.PatientInfoElectronicHandler;
import com.hospital.ecard.patienthandler.PatientInfoExecute;
import com.hospital.ecard.patienthandler.PatientInfoHandler;
import com.hospital.ecard.patienthandler.PatientInfoNewHandler;
import com.hospital.ecard.task.SetWorkKeyScheduled;
import com.hospital.ecard.xmlutils.SoapUtil;
import com.hospital.ecard.xmlutils.SyncCardInfoAndOperatorLogEHCSoapXmlUtils;
import lombok.extern.slf4j.Slf4j;
import lombok.val;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author lvyao
 * @description 电子健康卡处理
 * @date 2020/7/7
 */

@Slf4j
public class ECardHandler implements CardHandler {

    private static final int RESULT_VALUE = 10000;

    private AuthKey authKey = SpringContextHolder.getBean(AuthKey.class);

    private static RemoteUrl remoteUrl = SpringContextHolder.getBean(RemoteUrl.class);

    private DingDingProperty dingDingProperty = SpringContextHolder.getBean(DingDingProperty.class);

    private RestTemplate restTemplate = SpringContextHolder.getBean(RestTemplate.class);

    private PatientInfoService patientInfoService = SpringContextHolder.getBean(PatientInfoService.class);


    @Override
    public String dealCardInfo(BarcodeLogEntity barcodeLogEntity, HttpServletRequest request) {
        PatientInfo patientInfo = null;
        ResponseEntity<PatientInfo> cardInfoResEntityResponseEntity = new ResponseEntity<>();
        String healthCode = barcodeLogEntity.getIdentityNo().split(":")[0];
        List<PatientInfo> patientInfoList = patientInfoService.selectPatientInfoByIdNo(healthCode);
        if (barcodeLogEntity.getIdentityNo() != null && healthCode != null && !patientInfoList.isEmpty()) {
            patientInfo = patientInfoList.get(0);
            cardInfoResEntityResponseEntity.setBusinessInfo(patientInfo);
            cardInfoResEntityResponseEntity.setIsSuccess(10000);
            if ("0".equals(patientInfoService.getEchEffectSoft())) {
                //查询多个绑定不提示更新多余信息 20210830
                if (patientInfoList.size() > 1) {
                    boolean updateMoreInfo = updateMoreInfo(patientInfoList, patientInfo);
                    if (!updateMoreInfo) {
                        cardInfoResEntityResponseEntity.setIsSuccess(10006);
                        cardInfoResEntityResponseEntity.setBusinessInfo(null);
                        cardInfoResEntityResponseEntity.setErrMsg("EchEffectSoft参数未开启，更新多余的绑定信息失败！");
                    }
                    return JSONObject.toJSONString(cardInfoResEntityResponseEntity, SerializerFeature.WriteMapNullValue);
                }
            }
        }
        CardInfoResEntity cardInfoResEntity = null;
        try {
            if (!"0".equals(patientInfoService.getEchEffectSoft())) {
                //20220409 更换获取电子健康卡信息方式
//                String authKeyStr = PatientInfoHandler.getAuthKey();
                JSONObject jsonObject = null;
                String personCardByInfoNew = "";
                boolean isNewArrived = false;
                if (barcodeLogEntity.getIdentityNo().contains(":1:")||barcodeLogEntity.getIdentityNo().contains(":0:")) {
                    String authKeyStr = SetWorkKeyScheduled.setWorkKey();
                    if (StringUtils.isEmpty(authKeyStr)) {
                        throw new RuntimeException("无法获取到验证码");
                    }
                    BarcodeLogEntity barcodeLogEntity1 = barcodeLogEntity;
                    if (barcodeLogEntity.getOperatorCode() == null || barcodeLogEntity.getOperatorCode().equals("")) {
                        barcodeLogEntity1 = new BarcodeLogEntity();
                    }
                    EcardQRcodeInfo ecardQRcodeInfo = new EcardQRcodeInfo();
                    ecardQRcodeInfo.setQrCodeText(barcodeLogEntity.getIdentityNo());
                    EcardLogInfo ecardLogInfo = new EcardLogInfo();
                    ecardLogInfo.setOrgCode(barcodeLogEntity1.getUseOrgCode());
                    ecardLogInfo.setOpPersonCode(barcodeLogEntity1.getOperatorCode());
                    ecardLogInfo.setOpPersonName(barcodeLogEntity1.getOperatorName());
                    ecardLogInfo.setUseType("1");
                    ecardLogInfo.setOpTime(DateUtil.getTime());
                    EcardMedicalLog ecardMedicalLog = new EcardMedicalLog();
                    ecardMedicalLog.setMedicalStepCode(barcodeLogEntity1.getMedStepCode());
                    ecardMedicalLog.setUseDepCode(barcodeLogEntity1.getDepartmentCode());
                    ecardMedicalLog.setUseDepName(barcodeLogEntity1.getDepartmentName());
                    ecardMedicalLog.setUseDepGbCode(barcodeLogEntity1.getDepartmentCode());
                    ecardLogInfo.setMedical(ecardMedicalLog);
                    ecardQRcodeInfo.setLogInfo(ecardLogInfo);
                     personCardByInfoNew = getPersonCardByInfoNew(JSON.toJSONString(ecardQRcodeInfo), "2");
                     jsonObject = JSON.parseObject(personCardByInfoNew);
                }
                if (jsonObject != null&&!jsonObject.containsKey("virId")) {
                    cardInfoResEntityResponseEntity.setIsSuccess(10008);
                    cardInfoResEntityResponseEntity.setErrMsg("根据二维码获取患者电子健康卡信息失败！返回：" + personCardByInfoNew);

                } else {
                    EcardQRcodeResponse ecardQRcodeResponse = JSON.parseObject(personCardByInfoNew, EcardQRcodeResponse.class);
                    if (ecardQRcodeResponse !=null &&!StrKit.isBlank(ecardQRcodeResponse.getCardNo())) {
                        List<PatientInfo> list = patientInfoService.selectPatientInfoByIdNo(ecardQRcodeResponse.getCardNo().toUpperCase());
                        if (list != null && list.size() > 0) {
                            String val = barcodeLogEntity.getIdentityNo().substring(0, barcodeLogEntity.getIdentityNo().indexOf(":"));
                            List<PatientInfo> collect = list.stream().filter(c -> c.getHealthCardId() != null && c.getHealthCardId().equals(val)).collect(Collectors.toList());
                            if (!collect.isEmpty()) {
                                if (collect.size() > 1) {
                                    patientInfo = null;
                                } else {
                                    patientInfo = collect.get(0);
                                }
                            } else {
                                patientInfo = list.get(0);
                            }
                        } else {
                            isNewArrived = true;
                            patientInfo = new PatientInfo();
                            patientInfo.setName(ecardQRcodeResponse.getName());
                            int genderVal = Integer.parseInt(ecardQRcodeResponse.getSexCode());
                            patientInfo.setSex(genderVal == 1 ? "男" : genderVal == 2 ? "女" : "未知");
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                            patientInfo.setDateOfBirth(sdf.parse(ecardQRcodeResponse.getBirthday()));
                            patientInfo.setIdNo(ecardQRcodeResponse.getCardNo().toUpperCase());
                            patientInfo.setPhoneNumberHome(ecardQRcodeResponse.getPhoneNum());
                            if (ecardQRcodeResponse.getCardNo().length() > 15) {
                                patientInfo.setBirthPlace(ecardQRcodeResponse.getCardNo().substring(0, 6));
                            }
                            if (patientInfo.getNamePhonetic() == null) {
                                String pinY = PinYinKit.getHanziInitials(ecardQRcodeResponse.getName());
                                patientInfo.setNamePhonetic(pinY.replace(':', ' ').toUpperCase());
                            }
                            patientInfo.setLastVisitDate(new Date());
                        }
                        if (patientInfo != null) {
                            PatientInfoHandler.updatePatientInfo(patientInfo, isNewArrived);
                        }
                    }
                }

            }
            if (patientInfo == null) {
                //若是二维码格式只有healthCardId 前提是在所属集团下某医院已注册过信息的患者 继续新建到入参的医院主索引中
                if (barcodeLogEntity.getType() == 1) {
                    PatientInfo patientInfoEsb = getHealthIdInfo(barcodeLogEntity);
                    if (patientInfoEsb == null) {
                        cardInfoResEntityResponseEntity.setIsSuccess(10007);
                        cardInfoResEntityResponseEntity.setErrMsg("根据healthCardId未能从平台获取消息！");
                    } else {
                        cardInfoResEntityResponseEntity.setBusinessInfo(patientInfoEsb);
                        patientInfoList = patientInfoService.selectPatientInfoByIdNo(patientInfoEsb.getHealthCardId());
                        cardInfoResEntityResponseEntity.setIsSuccess(10000);
                    }
                } else {
                    cardInfoResEntityResponseEntity.setIsSuccess(10007);
                    cardInfoResEntityResponseEntity.setErrMsg("电子健康卡平台返回：" + cardInfoResEntity);
                }
            } else {
                cardInfoResEntityResponseEntity.setIsSuccess(cardInfoResEntity == null ? 10000 : cardInfoResEntity.getResultCode());
                cardInfoResEntityResponseEntity.setErrMsg(cardInfoResEntity != null ? "" + cardInfoResEntity : "");
                cardInfoResEntityResponseEntity.setBusinessInfo(patientInfo);
            }
        } catch (JSONException ex1) {
            cardInfoResEntityResponseEntity.setIsSuccess(10005);
            cardInfoResEntityResponseEntity.setErrMsg("网络IO出错");
            asyncSendMessage("包名：" + CardController.class.getPackage().getName() + "\r\n"
                    + "发生错误IP:" + request.getRemoteHost() + "\r\n错误信息:" + ex1.getMessage());
        } catch (Exception ex) {
            log.error("报错信息:" +  "入参："+ JSON.toJSONString(barcodeLogEntity), ex);
            cardInfoResEntityResponseEntity.setIsSuccess(10002);
            cardInfoResEntityResponseEntity.setErrMsg(ex.getMessage());
        }

//查询多个绑定不提示更新多余信息 20210830
        if (patientInfoList.size() > 1) {
            boolean updateMoreInfo = updateMoreInfo(patientInfoList, cardInfoResEntityResponseEntity.getBusinessInfo());
            if (!updateMoreInfo) {
                cardInfoResEntityResponseEntity.setIsSuccess(10008);
                cardInfoResEntityResponseEntity.setBusinessInfo(null);
                cardInfoResEntityResponseEntity.setErrMsg("更新多余的绑定信息失败！");
            }
        }
        //增加判断若是有患者信息就返回10000 20220509
        if (cardInfoResEntityResponseEntity.getBusinessInfo() != null && cardInfoResEntityResponseEntity.getBusinessInfo().getPatientId() != null) {
            cardInfoResEntityResponseEntity.setIsSuccess(10000);
        }
        if (cardInfoResEntityResponseEntity.getIsSuccess() != 10000) {
            log.error("请求：====" + JSON.toJSONString(barcodeLogEntity) + "========返回：" + JSON.toJSONString(cardInfoResEntityResponseEntity));
        }
        String str = JSONObject.toJSONString(cardInfoResEntityResponseEntity, SerializerFeature.WriteMapNullValue);
        return str;
    }


    @Async
    public void operatorLogEHCProcess(OperatorLogInfoEHC operatorLogInfoEHC) {
        String authKeyStr = PatientInfoHandler.getAuthKey();
        if (StringUtils.isEmpty(authKeyStr)) {
            throw new RuntimeException("无法获取到验证码");
        }
        StringBuffer logXmlStr = SyncCardInfoAndOperatorLogEHCSoapXmlUtils.syncCardInfoAndOperatorLogEHCSoapXml(operatorLogInfoEHC, authKeyStr, authKey.getOrgCode(), "operatorLogEHC");
        try {
            ResultEntity resultEntity = SoapUtil.getWebReturnResult(remoteUrl.getUrl(), logXmlStr, "operatorLogEHCResponse", ResultEntity.class);
            log.error(JSON.toJSONString(resultEntity));
            if (resultEntity != null && resultEntity.getResultCode().equals("10000")) {
                log.info(JSON.toJSONString(operatorLogInfoEHC) + "日志写入成功");
            } else {
                throw new RuntimeException(resultEntity.getMessage());
            }
        } catch (Exception ex) {
            log.error("日志提交报错信息:" + ex.getMessage());
        }
    }

    @Async
    public void asyncSendMessage(String s) {
        Map<String, Object> map = new HashMap<>();
        map.put("content", s);
        map.put("isAtAll", false);
        map.put("mobileList", new ArrayList<>());
        String url = String.format("%s:%s%s", dingDingProperty.getUrl(), dingDingProperty.getPort(), dingDingProperty.getPath());
        org.springframework.http.ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(url, map, String.class);
        log.info(stringResponseEntity.toString());
    }

    public PatientInfo getHealthIdInfo(BarcodeLogEntity barcodeLogEntity) {
        String healthGetInforUrl = patientInfoService.getHealthIdInfoUrl();
        if (healthGetInforUrl.equals("") || healthGetInforUrl == null) {
            log.info("数据库未查找到配置的HEALTH_ID_URL，请先配置！");
            return null;
        }
        PatientReqEntity patientReqEntity = null;
        try {
        String url = healthGetInforUrl + "?accessToken=" + getAccessToken() + "&healthCardId=" + barcodeLogEntity.getIdentityNo().split(":")[0];
            log.info("请求‘/getHealthCardInfo’接口入参原数据：" + barcodeLogEntity + "-------------get地址" + url);
        org.springframework.http.ResponseEntity<JSONObject> response = restTemplate.getForEntity(url, JSONObject.class);
        JSONObject body = response.getBody();

            if (body.getString("code").equals("0000")) {
                JSONObject result = body.getJSONObject("result");
                patientReqEntity = JSON.parseObject(result.toJSONString(), PatientReqEntity.class);
            } else {
                log.info(body.getString("msg") + "-------------通过HEALTHCARDID获取信息平台返回：" + body);
                return null;
            }
        } catch (Exception e) {
            log.info(e.getMessage());
            return null;
        }
        PatientInfoElectronicHandler patientInfoElectronicHandler = new PatientInfoNewHandler();
        PatientInfoExecute patientInfoExcute = new PatientInfoExecute(patientInfoElectronicHandler);
        PatientInfo patientInfo;
        try {
//            int genderVal = Integer.parseInt(patientReqEntity.getSex());
//            patientReqEntity.setSex(genderVal == 1 ? "男" : genderVal == 2 ? "女" : "未知");
            patientInfo = patientInfoExcute.execute(patientReqEntity);
        } catch (Exception e) {
            return null;
        }
        return patientInfo;
    }

    /**
     * 获取touken
     *
     * @return
     */
    public String getAccessToken() {
        String accessToken = "";
        try {
            String url = patientInfoService.getAccessTokenUrl() + "?clientId=hthis&clientSecret=hthis";
            org.springframework.http.ResponseEntity<JSONObject> response = restTemplate.getForEntity(url, JSONObject.class);
            JSONObject convertValue = response.getBody();
            accessToken = convertValue.getString("accessToken");
        } catch (Exception e) {
            log.error(e.toString() + "获取token失败");
        }
        return accessToken;
    }

    /**
     * @param patientInfos 数据库查询出的list
     * @param patientInfo  准备返回给前端的患者信息
     * @return
     */
    public boolean updateMoreInfo(List<PatientInfo> patientInfos, PatientInfo patientInfo) {
        for (PatientInfo patientInfoClear : patientInfos) {
            if (!patientInfoClear.getPatientId().equals(patientInfo.getPatientId())) {
                patientInfoClear.setHealthCardId("");
                patientInfoClear.setPHid("");
                patientInfoClear.setQrCodeText("");
                patientInfoClear.setAdminExt("");
                patientInfoClear.setVirtualCardNum("");
                boolean updateById = patientInfoService.updateById(patientInfoClear);
                if (!updateById) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * WEBAPI注册电子健康卡,或根据二维码获得电子健康卡信息
     *
     * @param ecardRegister
     * @return
     */
    public static String getPersonCardByInfoNew(String ecardRegister, String type) throws Exception {
        String authKeyStr = null;
        if (RedisUtils.isExistsKey("workKey")) {
            authKeyStr = RedisUtils.getKey("workKey");

        } else {
            authKeyStr = SetWorkKeyScheduled.setWorkKey();
        }
        if (StringUtils.isEmpty(authKeyStr)) {
            throw new RuntimeException("无法获取到验证码");
        }
        Tip resultAll = null;
        ResponseEntity<RegisterResEntity> returnVal = new ResponseEntity<>();
        String resultStr = null;
        String body = AESUtils.encrypt(ecardRegister, authKeyStr);

        try {
            val newUrl = remoteUrl.getNewUrl(type);
//            log.info("注册患者信息入参：" + ecardRegister + "====加密后：" + body);
            HttpResponse accessId = HttpRequest.post(newUrl).body(body).header("accessId", remoteUrl.getAccessId()).header("Content-Type", "application/json").execute();
//            log.info("注册患者信息返回内容：" + accessId.body());
            String reVal = AESUtils.decrypt(accessId.body(), authKeyStr);
            if (reVal == null){
                authKeyStr = SetWorkKeyScheduled.setWorkKey();
            }
            String code =reVal!=null&&JSON.parseObject(reVal).containsKey("code")? JSON.parseObject(reVal).getString("code"):null;
            if (code == null || !code.equals("10000")) {
                resultStr = reVal;
            } else {
                resultAll = JSON.parseObject(reVal, Tip.class);
                resultStr = resultAll.getData().toString();
                if (type.equals("1")) {
                    RegisterResEntity registerResEntity = new RegisterResEntity();
                    registerResEntity.setHealthCardId(JSON.parseObject(resultStr).getString("virId"));
                    registerResEntity.setVirtualCardNum(JSON.parseObject(resultStr).getString("virCardNo"));
                    resultStr = JSON.toJSONString(registerResEntity);
                }
            }

        } catch (Exception ex) {
            log.error("报错信息:===type:"+type+"===方法入参："+ JSON.toJSONString(ecardRegister), ex);
            returnVal.setIsSuccess(10002);
            returnVal.setErrMsg("运行中异常");
            throw ex;
        }
        return resultStr;
    }

}
